"""."""

from typing import Any

class LexiconMeta(type):
    def __new__(cls, name, bases, dct) -> object:
        _tooltips = {}
        for attr_name, attr_value in dct.items():
            if isinstance(attr_value, tuple):
                attr_name = attr_value[1]
                attr_value = attr_value[0]
            _tooltips[attr_value] = attr_name
        dct["_tooltipsDB"] = _tooltips
        return super().__new__(cls, name, bases, dct)

    def __getattribute__(cls, name) -> Any | None:
        parts = name.split(".")
        value = super().__getattribute__(parts[0])
        if type(value) == tuple:
            try:
                idx = int(parts[-1])
                value = value[idx]
            except:
                value = value[0]
        return value

class Lexicon(metaclass=LexiconMeta):
    ALPHA = "alpha", "Alpha blending value"
    ABSOLUTE = "absolute", "Return the absolute value of the input"
    ADAPT = "adapt", "Adapt"
    ALIGN = "align", "Top, Center or Bottom alignment"
    AMOUNT = "amount", "Amount"
    AMP = "amp", "Amplitude"
    ANGLE = "angle", "Rotation Angle"
    ANY = "🔮", "Any Type"
    ANY_OUT = "🦄", "Any Type"
    API = "API", "API URL route"
    ATTRIBUTE = "ATTRIBUTE", "The token attribute to use for authenticating"
    AUTH = "auth", "Authentication Bearer Token"
    AUTOSIZE = "autosize", "Scale based on Width & Height"
    AXIS = "axis", "Choose the direction in which to stack the images. Options include horizontal, vertical, or a grid layout"
    BATCH = "batch", "Output as a BATCH (all images in a single Tensor) or as a LIST of images (each image processed separately)"
    BBOX = "bbox", "Define an inner bounding box using relative coordinates [0..1] as a box region to clip."
    BITS = "bits", "How many numerical bits (0 or 1) to return"
    BLBR = "bl-br", "Bottom Left - Bottom Right"
    BLUR = "blur", "Blur"
    BOOLEAN = "bool", "Boolean"
    BOTTOM = "bottom", "Bottom"
    BPM = "bpm", "The number of Beats Per Minute"
    BRIGHTNESS = "brightness", "How bight"
    C1 = "c1", "Color Scheme Result 1"
    C2 = "c2", "Color Scheme Result 2"
    C3 = "c3", "Color Scheme Result 3"
    C4 = "c4", "Color Scheme Result 4"
    C5 = "c5", "Color Scheme Result 5"
    CAMERA = "camera", "Camera"
    CHAN = "chan", "Image Channels"
    CHAN_ALPHA = "🤍", "Alpha channel"
    CHAN_BLUE = "💙", "Blue channel"
    CHAN_GREEN = "💚", "Green channel"
    CHAN_RED = "❤️", "Red channel"
    CHANNEL = "chan", "Channel"
    CLIENT = "client", "Client area"
    COLOR = "color", "Color Entry for Gradient"
    COLORMAP = "colormap", "One of two dozen CV2 Built-in Colormap LUT (Look Up Table) Presets"
    COLUMNS = "cols", "0 = Auto-Fit, >0 = Fit into N columns"
    CONTRAST = "contrast", "Contrast"
    CONTROL = "control", "Control"
    COUNT = "count", "Number of things"
    CURRENT = "current", "Current"
    DATA = "data", "Data"
    DEFAULT = "default", "Default values for missing data"
    DEFAULT_A = "aa", "Default value for input a"
    DEFAULT_B = "bb", "Default value for input b"
    DEFICIENCY = "mode", "Type of color deficiency: Red (Protanopia), Green (Deuteranopia), Blue (Tritanopia)"
    DELAY = "delay", "Delay"
    DELTA = "delta", "Delta"
    DEPTH = "depth", "Grayscale image representing a depth map"
    DEVICE = "device", "Device"
    DICT = "dict", "Dictionary"
    DIFF = "diff", "Difference"
    DPI = "dpi", "Use DPI mode from OS"
    DYNAMIC = "❔", "Variable input with unknown value type"
    EASE = "ease", "Easing function"
    EDGE = "edge", "Clip or Wrap the Canvas Edge"
    EDGE_X = "edge_x", "Clip or Wrap the Canvas Edge"
    EDGE_Y = "edge_y", "Clip or Wrap the Canvas Edge"
    ELEVATION = "elevation", "Elevation angle of the light"
    ENABLE = "enable", "Enable or Disable"
    END = "end", "End of the range"
    EQUALIZE = "equalize", "Equalize an image"
    EXPOSURE = "exposure", "Exposure level"
    FAIL = "fail", "A failure condition"
    FALSE = "false", "False"
    FILEN = "filen", "File Name"
    FILL = "fill", "Fill values for the output with the default entry, only fill the zero values, or fill all remaining value fields (VEC*) with the calculated value"
    FILTER = "filter", "Filter"
    FIND = "find", "Find"
    FIXED = "fixed", "Fixed"
    FLIP = "flip", "Flip image top-to-bottom"
    FLOAT = "float", "Float"
    FOCAL = "focal", "Focal Length"
    FOCUS = "focus", "Focus"
    FOLDER = "folder", "Folder"
    FONT = "font", "Available System Fonts"
    FONT_SIZE = "size", "Text Size"
    FORMAT = "format", "Format"
    FPS = "fps", "Frames per second"
    FRAME = "frame", "Frame"
    FREQ = "freq", "Frequency"
    FUNCTION = "func", "Operation to perform on the input"
    FUZZ = "fuzz", "The fuzziness use to extend the start and end range(s)"
    GAMMA = "gamma", "Gamma"
    GRADIENT = "gradient", "Gradient"
    HEADING = "heading", "Direction of light"
    HEIGHT = "height", "Height"
    HI = "hi", "High / Top of range"
    HOLD = "hold", "Hold"
    HSV = "hsv", "Hue, Saturation and Value"
    IMAGE = "image", "RGBA, RGB or Grayscale image"
    IMAGE_BACK = "back", "RGBA, RGB or Grayscale image for background plate"
    IMAGE_FORE = "fore", "RGBA, RGB or Grayscale image for foreground overlay"
    IMAGE_SOURCE = "source", "Pixel Data (RGBA, RGB or Grayscale)"
    IMAGE_TARGET = "target", "Pixel Data (RGBA, RGB or Grayscale)"
    IN_A = "a", "Input A"
    IN_B = "b", "Input B"
    INDEX = "index", "Current item index in the Queue list"
    INT = "int", "Integer"
    INPUT = "input", "Automatically conform the inputs"
    INVERT = "invert", "Invert the output"
    IO = "io", "File I/O"
    ITERATION = "iter", "How many times (iterations) to perform the selected function"
    JUSTIFY = "justify", "How to align the text to the side margins of the canvas: Left, Right, or Centered"
    KEY = "key", "Key"
    LEFT = "left", "Left"
    LENGTH = "length", "Length"
    LENGTH2 = "all", "All items"
    LETTER = "letter", "If each letter be generated and output in a batch"
    LEVEL = "level", "Histogram levels"
    LINEAR = "linear", "Linear"
    LIST = "list", "List"
    LMH = "lmh", "Low, Middle, High"
    LO = "lo", "Low"
    LOHI = "lo-hi", "Low and High"
    LOOP = "loop", "Loop"
    LUT = "lut", "Size of each output lut palette square"
    MAP = "map", "Custom image that will be transformed into a LUT or a built-in cv2 LUT"
    MARGIN = "margin", "Whitespace padding around canvas"
    MASK = "mask", "Mask or Image to use as Mask to control where adjustments are applied"
    MATTE = "matte", "Background color for padding"
    MAX = "max", "Maximum"
    META = "meta", "Extra metadata to save in the file"
    MID = "mid", "Middle"
    MIDI = "midi", "Midi"
    MIRROR = "mirror", "Mirror"
    MODE = "mode", "Decide whether the images should be resized to fit a specific dimension. Available modes include scaling to fit within given dimensions or keeping the original size"
    MONITOR = "monitor", "Monitor"
    MSB = "msb", "Most signifigant bits"
    NAME = "name", "Filename of the output"
    NORMALIZE = "norm", "Normalize output values. \nMINMAX1 (0..1)\nMINMAX2 (-1..1)\nZSCORE (Standard Score)\nL2 (Unit Vector)"
    NOISE = "noise", "Noise"
    NOTE = "note", "Note"
    OFFSET = "offset", "Offset"
    ON = "on", "On"
    OPTIMIZE = "opt", "Optimize"
    ORIENT = "orent", "Orientation"
    OVERWRITE = "overwrite", "Overwrite"
    PAD = "pad", "Padding"
    PALETTE = "palette", "Palette"
    PARAM = "param", "Parameters"
    PASS_IN = "in", "Pass In"
    PASS_OUT = "out", "Pass Out"
    PATH = "path", "Destination path to save the output"
    PAUSE = "pause", "Pause"
    PERSPECTIVE = "perspective", "Perspective"
    PHASE = "phase", "Phase"
    PINGPONG = "pingpong", "Reverse the action when it reaches the loop point"
    PIVOT = "pivot", "Pivot"
    PIXEL = "image", "Pixel Data (RGBA, RGB or Grayscale)"
    PIXEL_A = "image_a", "Pixel Data (RGBA, RGB or Grayscale)"
    PIXEL_B = "image_b", "Pixel Data (RGBA, RGB or Grayscale)"
    PREFIX = "prefix", "Prefix"
    PRESET = "preset", "Preset"
    PROJECTION = "proj", "Projection"
    QUALITY = "quality", "Quality"
    QUALITY_M = "motion", "Motion Quality"
    QUEUE = "queue", "Current items to process during Queue iteration."
    RADIUS = "radius", "Radius"
    RANDOM = "random", "Random"
    RANGE = "range", "start index, ending index (0 means full length) and how many items to skip per step"
    RATE = "rate", "Rate"
    RECORD = "record", "Arm record capture from selected device"
    REGION = "region", "Region"
    RECURSE = "recurse", "Search within sub-directories"
    REPLACE = "replace", "String to use as replacement"
    RESET = "reset", "Reset"
    REVERSE = "reverse", "Reverse the calculated output"
    RIGHT = "right", "Right"
    ROTATE = "rotate", "Rotation Angle"
    ROUND = "round", "Round to the nearest decimal place, or 0 for integer mode"
    ROUTE = "route", "Pass through another route node to pre-populate the outputs"
    SAMPLE = "sample", "Method for resizing images."
    SCALAR = "scalar", "Scale of the range after normalization"
    SCHEME = "scheme", "Scheme"
    SEED = "seed", "Random generator's initial value"
    SEGMENT = "segment", "Number of parts which the input image should be split"
    SELECT = "select", "Select"
    SHAPE = "shape", "Circle, Square or Polygonal forms"
    SHIFT = "shift", "Shift"
    SIDES = "sides", "Number of sides polygon has (3-100)"
    SOLVER = "solver", "Solver to use when translating to new color space"
    SIZE = "size", "Scalar by which to scale the input"
    SKIP = "skip", "Interval between segments"
    SPACING = "spacing", "Line Spacing between Text Lines"
    START = "start", "Start of the range"
    STEP = "step", "Steps/Stride between pulses -- useful to do odd or even batches. If set to 0 will stretch from (VAL -> LOOP) / Batch giving a linear range of values."
    STOP = "stop", "Halt processing"
    STRENGTH = "strength", "Strength"
    STRING = "string", "String Entry"
    STYLE = "style", "Style"
    SUCCESS = "success", "A successful condition"
    SWAP = "swap", "Swap inputs"
    SWAP_A = "swap a", "Replace input Alpha channel with target channel or constant"
    SWAP_B = "swap b", "Replace input Blue channel with target channel or constant"
    SWAP_G = "swap g", "Replace input Green channel with target channel or constant"
    SWAP_R = "swap r", "Replace input Red channel with target channel or constant"
    SWAP_W = "swap w", "Replace input W channel with target channel or constant"
    SWAP_X = "swap x", "Replace input Red channel with target channel or constant"
    SWAP_Y = "swap y", "Replace input Red channel with target channel or constant"
    SWAP_Z = "swap z", "Replace input Red channel with target channel or constant"
    THICK = "thick", "Thickness"
    THRESHOLD = "threshold", "Threshold"
    TILE = "tile", "Title"
    TIME = "time", "Time"
    TIMEOUT = "timeout", "Time (in seconds) to wait reading the source before timing out"
    TIMER = "timer", "Timer"
    TLTR = "tl-tr", "Top Left - Top Right"
    TOGGLE = "toggle", "Toggle"
    TOP = "top", "Top"
    TOTAL = "total", "Total items in the current Queue List"
    TRIGGER = "trigger", "Trigger"
    TRUE = "true", "True"
    TYPE = "type", "Convert input type to the selected type"
    URL = "url", "URL"
    USER = "user", "Custom user metadat to save with the file"
    V = "value", "Value"
    VALUE = "value", "Value"
    VEC = "vector", "Compound value of type float, vec2, vec3 or vec4"
    W = "w", "W"
    WAIT = "wait", "Wait"
    WAVE = "wave", "Wave Function"
    WH = "wh", "Width and Height"
    WHC = "whc", "Width, Height and Channel as a Vector3 (x,y,z)"
    WIDTH = "width", "Width"
    WINDOW = "window", "Window"
    X = "x", "X"
    XY = "xy", "X and Y"
    XYZ = "xyz", "X, Y and Z (VEC3)"
    XYZW = "xyzw", "X, Y, Z and W (VEC4)"
    Y = "y", "Y"
    Z = "z", "Z"
    ZOOM = "zoom", "Zoom level"

    @classmethod
    def _parse(cls, node: dict) -> dict[str, str]:
        for cat, entry in node.items():
            if cat not in ["optional", "required"]:
                continue
            for k, v in entry.items():
                if (widget_data := v[1] if isinstance(v, (tuple, list,)) and len(v) > 1 else None) is None:
                    continue
                if (tip := widget_data.get("tooltip", None)):
                    continue
                if (tip := cls._tooltipsDB.get(k, None)) is None:
                    continue
                widget_data["tooltip"] = tip
                node[cat][k] = (v[0], widget_data)
        return node
